<template>
  <div id="app">
    <el-row>
      <el-col :span="span">
        <div class="rainbow-text">
          swagger转API工具
        </div>
        <el-form
          v-if="apiModule"
          ref="form"
          class="form"
          :rules="rules"
          :model="config"
          label-width="100px"
          label-position="right"
        >
          <el-form-item label="json:" prop="json" style="width: 100%; margin-top: 10px">
            <el-input v-model="config.json" placeholder="输入swagger的json" :rows="5" type="textarea" clearable></el-input>
          </el-form-item>

          <el-form-item label="importPath:" prop="importPath">
            <el-input v-model="config.importPath" clearable></el-input>
          </el-form-item>
        </el-form>
        <el-select
          v-if="!apiModule && apiData.modelLabel"
          v-model="selectValue"
          filterable
          style="width: 100%; margin-bottom: 20px"
        >
          <el-option
            v-for="(key, index) in Object.keys(model)"
            :key="index"
            :label="key"
            :value="key"
          ></el-option>
        </el-select>
        <!-- <el-form-item label="模块路径" prop="showModelPath">
          <el-switch v-model="config.showModelPath" />
        </el-form-item> -->
        <div class="submit flex justify-around ">
          <el-button type="primary" @click="make">
            提 交
          </el-button>
          <el-button plain @click="clearJson">
            清 空
          </el-button>
        </div>
        <div v-if="apiModule" class="list">
          <div v-if="apiData.api && Object.keys(apiData.api).length" class="api-box-warp">
            <el-button icon="Download" class="down-btn" @click="handleDownApi">
              下载API文件
            </el-button>
            <el-table
              ref="multipleTableRef"
              :data="Object.keys(apiData.api)"
              style="width: 100%"
              @selectionChange="handleSelectionChange"
              @cellClick="handleCellClick"
            >
              <el-table-column type="selection" width="50" />

              <el-table-column label="实体名称" width="300">
                <template #default="{ row }">
                  <div :class="`${active}` === `${row}` ? 'active-row' : ''">
                    {{ row }}
                  </div>
                </template>
              </el-table-column>
            </el-table>
          </div>
        </div>
      </el-col>
      <el-col :span="24 - span">
        <div class=" pos-r">
          <pre
            v-if="apiModule"
            class="line-numbers api"
          ><code v-html="result"></code></pre>
          <pre v-else class="line-numbers api vue"><code>{{ result }}</code></pre>
          <el-button
            v-if="result"
            class="pos-a"
            type="primary"
            @click="handleCopy"
          >
            复制
          </el-button>
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import Prism from 'prismjs'
import 'prismjs/themes/prism.css'
import copy from 'copy-to-clipboard'
import { makeForm } from './swaggerV1/service.js'
import { changSwaggerData, flatDefinitions } from '@/utils/swaggerUtil/swaggerData'
import { handleMapApiModel, mapApiModel } from '@/utils/swaggerUtil/index'
import { openapiJson } from '@/utils/swaggerUtil/swaggerJson'
import {
  outExportFolder,
} from '@/utils/downFile'
import { buildApiFile } from '@/utils/swaggerUtil/addApiCode'

export default {
  name: 'Index',
  data() {
    return {
      fileList: [],
      model: {},
      selectValue: '',
      apiModule: true,
      hasCopy: false,
      span: 6,
      config: {
        json: '',
        requestName: 'request',
        apiPrefix: '',
        importPath: 'import request from \'@/utils/request\'',
        modelLabel: false,
        showModelPath: true,
      },
      apiData: {},
      result: '',
      active: '',
      rules: {
        json: [
          { required: true, message: '请输入swagger的json', trigger: 'blur' },
        ],
        requestName: [
          { required: true, message: '请填写请求函数', trigger: 'blur' },
        ],
        importPath: [
          {
            required: true,
            message: '请填写导入请求函数语句',
            trigger: 'blur',
          },
        ],
      },
      selectList: [],
      apiJson: {},
      modelList: [],
      activeNames: '',
    }
  },
  mounted() {
    let useNum = window.localStorage.getItem('hasUseNum') || 0
    window.localStorage.setItem('hasUseNum', Number(useNum) + 1)
    if (useNum < 5) {
      this.$message.warning('默认使用示例json, 请清空后再输入文档的json')
      this.setDefaultJson()
    }
  },
  methods: {

    setDefaultJson() {
      this.config.json = JSON.stringify(openapiJson)
    },
    switchModule() {
      if (this.apiData.modelLabel == null) {
        this.$message.warning('请设置modelLabel为true, 提交后再切换')
        return
      }
      this.result = ''
      this.apiModule = !this.apiModule
      if (!this.apiModule) {
        try {
          this.model = eval(`(${this.apiData.modelLabel})`)
        } catch (err) {
          console.log(err)
          this.model = {}
        }
      }
    },
    selectChange(key) {
      try {
        let value = this.model[key]
        this.result = makeForm(value)
      } catch (err) {
        this.message.error('解析失败')
      }
    },

    fileRemove() {
      this.config.json = null
      this.fileList = []
    },
    make() {
      if (this.apiModule) {
        this.$refs.form.validate(async (valid) => {
          if (valid) {
            try {
              let apiJson = JSON.parse(this.replaceJson(this.config.json))
              let params = {
                ...this.config,
                json: apiJson,
              }
              this.apiJson = apiJson
              this.jsonToSwaggerTree(params, apiJson)
              let data = await changSwaggerData(params, this.modelList)

              this.apiData = data
              // this.$message.success('生成成功')
              this.$nextTick(() => {
                this.activeNames = ['api']
              })
            } catch (err) {
              console.error(err)
              this.$message.error(err || 'json格式数据有误！')
            }
          }
        })
      } else {
        this.selectChange(this.selectValue)
      }
    },

    keyClick(key1, key2) {
      this.active = key2
      let result = ''
      if (key1 === key2) {
        result = this.apiData[key1] || ''
      } else {
        result = this.apiData[key1][key2] || ''
      }
      this.code = result

      this.result = Prism.highlight(
        result,
        Prism.languages.javascript,
        'javascript',
      )
    },
    handleCellClick(e) {
      this.active = e
      let result = this.apiData['api'][e] || ''
      this.code = result
      if (result.length) {
        this.result = Prism.highlight(
          result,
          Prism.languages.javascript,
          'javascript',
        )
      } else {
        this.result = ''
      }
    },
    handleCopy() {
      if (copy(this.code)) {
        this.$message.success('代码已复制到剪贴板')
      } else {
        this.$message.error('代码复制有点问题?')
      }
    },
    clearJson() {
      this.config.json = ''
    },
    jsonToSwaggerTree(swaggerConfig, data) {
      try {
        let definitions = flatDefinitions(data.definitions)
        let modelList = handleMapApiModel(swaggerConfig, data.tags, definitions)
        this.modelList = modelList
      } catch (err) {
        console.log(err)
        this.$message.error('解析失败')
      }
    },
    handleSelectionChange(val) {
      this.selectList = val
    },

    handleDownApi() {
      if (!this.selectList.length) {
        this.$message.warning('请选择要下载的实体')
        return
      }
      try {
        const fileList = []
        this.selectList?.forEach((item) => {
          let model = this.modelList.find(i => i.tableCnName === item)
          let newTableName = model.tableName?.length > 4 ? model.tableName : model.tableName + model.structName
          let fileText = this.apiData['api'][item]
          let label = `${newTableName}/index.js`
          let itemFile = buildApiFile(label, fileText)
          fileList.push(itemFile)
        })
        outExportFolder('api', fileList)
        this.$message.success('下载成功')
      } catch (err) {
        console.log(err)
        this.$message.error('下载失败')
      }
    },

    replaceJson(str) {
      return str?.replace(/"example":\{(.*?)\}/g, '"example":""')
    },
  },
}
</script>

<style lang="scss" scoped>
#app {

  overflow: hidden;
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  .form{
    padding-left:12px;
  }
  .submit {
    padding-bottom: 20px;
    .el-button {
      width: 40%;
    }
  }
  .el-upload {
    width: 100%;
    .el-button {
      width: 100%;
    }
  }
   .el-upload-list {
    .el-upload-list__item {
      text-align: left;
    }
  }
  .list {
    height: 500px;
    border: 1px #ccc dashed;
    padding-bottom: 20px;
   .el-collapse-item__header {
      padding-left: 10px;
    }
    .item {
      text-align: left;
      padding: 10px 25px;
      cursor: pointer;
      border-bottom: 1px #f0f0f0 dashed;
    }
    .active {
      background: #67c04b;
      color: #fff;

    }
    overflow-y: scroll;
  }
  pre {
    text-align: left;
    padding: 20px;

    padding-left: 40px;
    background: #282c33;
    color: #ccc;
    border-top: 4px solid #67c04b;
    counter-reset: line;
    white-space: pre-wrap;
    word-break: break-all;
    span {
      display: block;
      line-height: 1.5rem;
    }
     span.token {
      background: none;
    }
  }
  .pos-r{
    position: relative;
  }
  .pos-a{
    position: absolute;
    right:28px;
    top:10px;
  }
  .left-collapse-title{
    padding-left:10px;
    font-size: 15px;
    font-weight: 600;
    color:#000;
  }
  .api {
    font-size: 14px;
    height: calc(92.5vh - 4px);
    margin: 0;
    margin-left: 20px;
    overflow-y: scroll;
    code {
      span {
        text-align: left;
      }
    }
  }
  .down-btn{
    margin-bottom: 10px;
  }
  .vue {
    color: #67c04b;
  }
}
.api-box-warp{
  padding-top: 20px;
  padding-bottom: 40px;
  margin-bottom: 10px;
}
.active-row{
  display: block;
  color: #fff;
  background: #67c04b;
  padding: 6px 5px;

}
.rainbow-text {
  margin-top:12px;
  font-size: 28px; /* 文字大点，效果更明显 */
  font-weight: bold; /* 文字粗点，这样效果更明显 */
  color: transparent; /* 设置文字填充颜色为透明，这样可以把背景显示出来 */
  -webkit-text-fill-color: transparent; /* 使用一个非标准的方法覆盖文字填充颜色，以防color被其他代码覆盖 */
  text-shadow: 2px -2px #000, 1px -1px #fff; /* 设置顶层黑色投影和中层白色投影 */
  background-image: linear-gradient(135deg, #fff 0%, #fff 25%, #000 25%, #000 50%, #fff 50%, #fff 75%, #000 75%, #000 100%);   /* 使用 #fff 和 #000 画出条纹效果，并倾斜135度 */
  background-size: 2px 2px; /* 背景图大小，控制斑马纹的粗细 */
  background-repeat: repeat; /* 不断重复渲染背景图 */
  -webkit-background-clip: text; /* 将背景渲染到文本中（兼容性写法） */
  background-clip: text; /* 将背景渲染到文本中 */

}
</style>
